import _ from 'lodash'
import {CtlBase} from "./CtlBase";
import {CtlTransformDefault} from "./CtlDefaultValue";
import {parseYvanPropChangeVJson} from "./CtlUtils";
import {CtlGrid, GridRefreshMode} from "./CtlGrid";
import * as YvanMessage from "./YvanUIMessage";

export class CtlTransform extends CtlBase<CtlTransform> {
    static create(module: any, vjson: any): CtlTransform {
        const that = new CtlTransform(_.cloneDeep(vjson))
        that._module = module

        _.defaultsDeep(vjson, CtlTransformDefault)

        if (vjson.hasOwnProperty('debugger')) {
            debugger
        }

        // 提取基础属性 onRender / ctlName / entityName 等等
        const yvanProp = parseYvanPropChangeVJson(vjson, [
            'invokeFunction',
            'idType',
            'idField',
            'check',
            'scene',
            'gridLeft',
            'gridRight',
        ])

        // 将 vjson 存至 _webixConfig
        that._webixConfig = vjson

        // 将 yvanProp 合并至当前 CtlBase 对象
        _.assign(that, yvanProp)

        // 删除 vjson 所有数据, 替换为 template 语法
        _.forOwn(vjson, (value, key) => {
            delete vjson[key]
        })


        const gleft = {
            ...yvanProp.gridLeft,
            view: 'grid',
            checkbox: true,
            idField: yvanProp.idField,
            onRender(sender: CtlGrid) {
                that.attachHandle(sender, {...vjson, ...yvanProp})
                that.gridLeft = sender
            },
            dataSource: {
                ...yvanProp.gridLeft.dataSource,
                extParams: {
                    scene: () => that.scene
                }
            }
        }

        const gright = {
            ...yvanProp.gridRight,
            columns: [
                ...(yvanProp.gridLeft.columns || []),
                ...(yvanProp.gridRight.columns || [])
            ],
            view: 'grid',
            checkbox: true,
            idField: yvanProp.idField,
            onRender(sender: CtlGrid) {
                that.gridRight = sender
            },
            dataSource: {
                ...yvanProp.gridRight.dataSource,
                extParams: {
                    scene: () => that.scene
                }
            }
        }


        // 将 事件与 _webixConfig 一起存至 vjson 交给 webix 框架做渲染
        _.merge(vjson, that._webixConfig, {
            cols: [
                {
                    cols: [
                        {
                            rows: [
                                gleft.toolbar,
                                gleft
                            ]
                        },
                        {
                            rows: [
                                {},
                                {
                                    view: 'button',
                                    icon: "fa fa-angle-double-right",
                                    width: 15,
                                    click: () => {
                                        that.doTransform(true)
                                    },

                                },
                                {
                                    view: 'button',
                                    icon: "fa fa-angle-double-left",
                                    click: () => {
                                        that.doTransform(false)
                                    },
                                },
                                {}
                            ]
                        }
                    ]
                },
                {view: 'resizer'},
                {
                    rows: [
                        gright.toolbar,
                        gright
                    ]
                }

            ]
        })

        return that
    }

    constructor(vjsonRaw: any) {
        super(vjsonRaw);
    }

    /**
     * 左边表
     */
    gridLeft!: CtlGrid

    /**
     * 右边表格
     */
    gridRight!: CtlGrid

    /**
     * 勾选时调用的后台方法，一般在 app.ts 里，用 YvanUI.CtlTransformDefault.invokeFunction 声明一个全局方法即可
     */
    invokeFunction!: (param: InvokeFunctionParam) => Promise<any>

    /**
     * 主键类型, 记录勾选的id主键可能是 long / text / int 中的一种，才能启用数据库索引
     */
    idType!: 'long' | 'text' | 'int'

    /**
     * 功能场景名称，全局唯一的名称，从数据库表中区分勾选的数据是用于哪个功能场景的
     */
    scene!: string

    /**
     * 左右表关联用的字段名称(必须是左右表的主键)
     */
    idField!: string

    /**
     * 判断是否允许穿梭
     */
    check!: boolean

    /**
     *
     * @param isCheck 等于 true 时就是点击向右(添加)按钮， false 时就是点击向左(删除)按钮
     */
    doTransform(isCheck: boolean) {
        const sender = this
        if (this.check) {
            if (isCheck) {
                // 勾选，从左边到右边去
                const rows = sender.gridLeft.getCheckedRows()
                const ids = _.map(rows, row => row[sender.gridLeft.idField])
                sender.invokeFunction({
                    ids,
                    scene: sender.scene,
                    method: 'check',
                    idType: sender.idType,
                }).then(() => {
                    sender.gridLeft.reload(GridRefreshMode.refreshWithFilter)
                    sender.gridRight.reload(GridRefreshMode.refreshWithFilter)
                })

            } else {
                // 取消勾选，从右边返回到左边
                const rows = sender.gridRight.getCheckedRows()
                const ids = _.map(rows, row => row[sender.gridRight.idField])
                sender.invokeFunction({
                    ids,
                    scene: sender.scene,
                    method: 'uncheck',
                    idType: sender.idType,
                }).then(() => {
                    sender.gridLeft.reload(GridRefreshMode.refreshWithFilter)
                    sender.gridRight.reload(GridRefreshMode.refreshWithFilter)
                })
            }
        } else {
            YvanMessage.msg('请先确定是否允许修改！')
        }
    }
}

export interface InvokeFunctionParam {
    ids: any[],
    scene: string,
    method: 'check' | 'uncheck',
    idType: 'long' | 'text' | 'int'
}